import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

import sk.upjs.ariadne.editor.MapLayer;
import sk.upjs.ariadne.editor.MapPanel;
import sk.upjs.ariadne.editor.data.IndoorMap;
import sk.upjs.ariadne.editor.maplayers.ImageLayer;
import sk.upjs.ariadne.editor.maplayers.WallLayer;

import javax.swing.DefaultListCellRenderer;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JSpinner;
import javax.swing.UIManager;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;

import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.SpinnerNumberModel;
import javax.swing.JList;
import javax.swing.border.BevelBorder;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;

public class TestFrame extends JFrame {

	private JPanel contentPane;
	private JTextField mapWidthField;
	private JTextField mapHeightField;
	private MapPanel mapPanel;
	private JList<MapLayer> layerList;
	private JPanel controlContainer;
	
	// Temporary development code
	private IndoorMap indoorMap;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager
							.getSystemLookAndFeelClassName());
					TestFrame frame = new TestFrame();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	@SuppressWarnings("serial")
	public TestFrame() {
		setTitle("Map Editor");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 835, 583);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);

		mapPanel = new MapPanel();

		JPanel topPanel = new JPanel();

		JPanel layerPanel = new JPanel();
		
		JPanel panel = new JPanel();
		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane.setHorizontalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addComponent(topPanel, GroupLayout.PREFERRED_SIZE, 774, Short.MAX_VALUE)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addComponent(layerPanel, GroupLayout.PREFERRED_SIZE, 144, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(mapPanel, GroupLayout.DEFAULT_SIZE, 624, Short.MAX_VALUE))
				.addComponent(panel, GroupLayout.DEFAULT_SIZE, 809, Short.MAX_VALUE)
		);
		gl_contentPane.setVerticalGroup(
			gl_contentPane.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_contentPane.createSequentialGroup()
					.addComponent(topPanel, GroupLayout.PREFERRED_SIZE, 65, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.RELATED)
					.addGroup(gl_contentPane.createParallelGroup(Alignment.LEADING)
						.addComponent(mapPanel, GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE)
						.addComponent(layerPanel, GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE))
					.addPreferredGap(ComponentPlacement.RELATED)
					.addComponent(panel, GroupLayout.PREFERRED_SIZE, 53, GroupLayout.PREFERRED_SIZE))
		);
		
		JPanel panel_1 = new JPanel();
		
		controlContainer = new JPanel();
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
					.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 143, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(ComponentPlacement.UNRELATED)
					.addComponent(controlContainer, GroupLayout.DEFAULT_SIZE, 656, Short.MAX_VALUE))
		);
		gl_panel.setVerticalGroup(
			gl_panel.createParallelGroup(Alignment.LEADING)
				.addComponent(panel_1, GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
				.addComponent(controlContainer, GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
		);
		controlContainer.setLayout(new BorderLayout(0, 0));
		panel.setLayout(gl_panel);

		layerList = new JList<MapLayer>();
		layerList.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				mapPanel.getMapLayers().setSelectedItem(
						layerList.getSelectedValue());
			}
		});

		layerList.setCellRenderer(new DefaultListCellRenderer() {
			@Override
			public Component getListCellRendererComponent(JList<?> list,
					Object value, int index, boolean isSelected,
					boolean cellHasFocus) {

				if (value != null) {
					value = ((MapLayer) value).getLayerName();
				}
				return super.getListCellRendererComponent(list, value, index,
						isSelected, cellHasFocus);
			}
		});

		layerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		layerList.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null,
				null, null));

		JLabel lblNewLabel_1 = new JLabel("Layers:");
		GroupLayout gl_layerPanel = new GroupLayout(layerPanel);
		gl_layerPanel.setHorizontalGroup(gl_layerPanel
				.createParallelGroup(Alignment.LEADING)
				.addGroup(
						gl_layerPanel.createSequentialGroup().addContainerGap()
								.addComponent(lblNewLabel_1)
								.addContainerGap(98, Short.MAX_VALUE))
				.addComponent(layerList, GroupLayout.DEFAULT_SIZE, 144,
						Short.MAX_VALUE));
		gl_layerPanel.setVerticalGroup(gl_layerPanel.createParallelGroup(
				Alignment.LEADING).addGroup(
				gl_layerPanel
						.createSequentialGroup()
						.addComponent(lblNewLabel_1)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(layerList, GroupLayout.PREFERRED_SIZE,
								323, GroupLayout.PREFERRED_SIZE)
						.addContainerGap(67, Short.MAX_VALUE)));
		layerPanel.setLayout(gl_layerPanel);

		mapWidthField = new JTextField();
		mapWidthField.setColumns(10);

		JLabel lblMapSize = new JLabel("Map width:");

		mapHeightField = new JTextField();
		mapHeightField.setColumns(10);

		JLabel lblNewLabel = new JLabel("Map height:");

		JButton btnUpdateSize = new JButton("Update size");
		btnUpdateSize.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				mapPanel.setMapSize(
						Double.parseDouble(mapWidthField.getText()),
						Double.parseDouble(mapHeightField.getText()));
			}
		});

		JLabel lblZoom = new JLabel("Zoom:");

		final JSpinner zoomSpinner = new JSpinner();
		zoomSpinner.setModel(new SpinnerNumberModel(1.0, 1.0, 100.0, 1.0));
		zoomSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent arg0) {
				mapPanel.setZoom((Double) zoomSpinner.getValue());
			}
		});

		JButton btnAutoSize = new JButton("Auto size");
		btnAutoSize.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				mapPanel.autoSize();
			}
		});
		
		JButton btnTestAction = new JButton("Test action");
		btnTestAction.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				indoorMap.saveTo(new File("mapa.xml"));
			}
		});
		GroupLayout gl_topPanel = new GroupLayout(topPanel);
		gl_topPanel.setHorizontalGroup(
			gl_topPanel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_topPanel.createSequentialGroup()
					.addContainerGap()
					.addGroup(gl_topPanel.createParallelGroup(Alignment.LEADING)
						.addGroup(gl_topPanel.createSequentialGroup()
							.addComponent(lblMapSize)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(mapWidthField, GroupLayout.PREFERRED_SIZE, 54, GroupLayout.PREFERRED_SIZE)
							.addGap(12)
							.addComponent(lblNewLabel)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(mapHeightField, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(btnUpdateSize)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(lblZoom)
							.addPreferredGap(ComponentPlacement.RELATED)
							.addComponent(zoomSpinner, GroupLayout.PREFERRED_SIZE, 65, GroupLayout.PREFERRED_SIZE)
							.addGap(18)
							.addComponent(btnTestAction))
						.addComponent(btnAutoSize))
					.addContainerGap(250, Short.MAX_VALUE))
		);
		gl_topPanel.setVerticalGroup(
			gl_topPanel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_topPanel.createSequentialGroup()
					.addGap(5)
					.addGroup(gl_topPanel.createParallelGroup(Alignment.BASELINE)
						.addComponent(lblMapSize)
						.addComponent(lblNewLabel)
						.addComponent(mapWidthField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(mapHeightField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(btnUpdateSize)
						.addComponent(lblZoom)
						.addComponent(zoomSpinner, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
						.addComponent(btnTestAction))
					.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
					.addComponent(btnAutoSize)
					.addContainerGap())
		);
		topPanel.setLayout(gl_topPanel);
		contentPane.setLayout(gl_contentPane);

		zoomSpinner.setValue(mapPanel.getZoom());
		mapWidthField.setText(Double.toString(mapPanel.getMapWidth()));
		mapHeightField.setText(Double.toString(mapPanel.getMapHeight()));

		mapPanel.getMapLayers().addListDataListener(new ListDataListener() {
			@Override
			public void intervalRemoved(ListDataEvent arg0) {
				updateControlPanel();
			}

			@Override
			public void intervalAdded(ListDataEvent arg0) {
				updateControlPanel();
			}

			@Override
			public void contentsChanged(ListDataEvent arg0) {
				updateControlPanel();
			}
		});

		ImageLayer bg = new ImageLayer();
		mapPanel.getMapLayers().addElement(bg);

		indoorMap = new IndoorMap();
		// indoorMap = new IndoorMap(new File("mapa.xml"));
		WallLayer walls = new WallLayer(indoorMap);
		mapPanel.getMapLayers().addElement(walls);
		
		layerList.setModel(mapPanel.getMapLayers());
		layerList.setSelectedValue(mapPanel.getMapLayers().getSelectedItem(), true);
	}

	private void updateControlPanel() {
		MapLayer layer = (MapLayer)mapPanel.getMapLayers().getSelectedItem();
		if (layer == null) {
			controlContainer.removeAll();
			controlContainer.revalidate();
			controlContainer.repaint();
			return;
		}

		JPanel oldControl = (controlContainer.getComponentCount() == 1) ? (JPanel) controlContainer
				.getComponent(0) : null;
				
		JPanel newControl = layer.getControlPanel();
		if (newControl == oldControl) {
			return;
		}

		controlContainer.removeAll();
		if (newControl != null)
			controlContainer.add(newControl, BorderLayout.CENTER);
		
		controlContainer.revalidate();
		controlContainer.repaint();
	}
}
